Polygons
In most simulations, such as Global Climate Models, Unstructured Grids are composed of nodes that are connected with edges to form faces that discretize the surface of a sphere (i.e. Earth).
For visualization, these faces can be geometrically represented as Polygons.
Setup
Imports
import uxarray as ux
file_dir = "../../meshfiles/"
/home/runner/miniconda3/envs/cookbook-dev/lib/python3.10/site-packages/dask/dataframe/_pyarrow_compat.py:17: FutureWarning: Minimal version of pyarrow will soon be increased to 14.0.1. You are using 12.0.1. Please consider upgrading.
warnings.warn(
Conversion Methods
UXarray represents Unstructured Grids through a set of coordinate and connectivity variables (i.e. node_lon, node_lat, face_node_connectivity, etc.). These variables can be manipulated to obtain our Polygons for visualuzation
Representation as a GeoDataFrame
Polygons are stored in a SpatialPandas GeoDataFrame, which is the expected data structured by the HoloViz stack of packages for visualizing polygons.
A Grid can be converted into a GeoDataFrame, which will contain a single “geometry” column, which is a series of Polygons that represent each face.
uxds_mpas.uxgrid.to_geodataframe()
| geometry | |
|---|---|
| 0 | MultiPolygon([[[-175.30886840820312, 27.001102... |
| 1 | MultiPolygon([[[-180.0, 89.4604645, -138.95294... |
| 2 | MultiPolygon([[[5.6199164390563965, -26.397180... |
| 3 | MultiPolygon([[[76.47418975830078, -26.3971805... |
| 4 | MultiPolygon([[[-30.380083084106445, 26.397180... |
| ... | ... |
| 28566 | MultiPolygon([[[-102.95294189453125, -52.62263... |
| 28567 | MultiPolygon([[[-104.75326538085938, -52.61119... |
| 28568 | MultiPolygon([[[-174.95294189453125, -52.62263... |
| 28569 | MultiPolygon([[[-174.04080200195312, -52.93654... |
| 28570 | MultiPolygon([[[-174.95294189453125, -52.62263... |
28571 rows × 1 columns
A UxDataArray can also be converted into a GeoDataFrame. It will now have an additional column containing a 1D-slice of data variable.
It’s important to note that to convert a UxDataArray into a GeoDataFrame, the dimension of the data variable must match the number of faces (a.k.a. mapped to faces) and there can not be any additional dimensions (i.e. time, level, etc.)
uxds_mpas["bottomDepth"].to_geodataframe()
| geometry | bottomDepth | |
|---|---|---|
| 0 | MultiPolygon([[[-175.30886840820312, 27.001102... | 4973.0 |
| 1 | MultiPolygon([[[-180.0, 89.4604645, -138.95294... | 4139.0 |
| 2 | MultiPolygon([[[5.6199164390563965, -26.397180... | 2639.0 |
| 3 | MultiPolygon([[[76.47418975830078, -26.3971805... | 4003.0 |
| 4 | MultiPolygon([[[-30.380083084106445, 26.397180... | 5403.0 |
| ... | ... | ... |
| 28566 | MultiPolygon([[[-102.95294189453125, -52.62263... | 3921.0 |
| 28567 | MultiPolygon([[[-104.75326538085938, -52.61119... | 4157.0 |
| 28568 | MultiPolygon([[[-174.95294189453125, -52.62263... | 5527.0 |
| 28569 | MultiPolygon([[[-174.04080200195312, -52.93654... | 5511.0 |
| 28570 | MultiPolygon([[[-174.95294189453125, -52.62263... | 5387.0 |
28571 rows × 2 columns
If a data variable is not face-centered, it can be manipulated to get it to map to faces. For node-centered data, as is the case with our Geoflow dataset, we can perform a nodal-average operation, which takes the average all the nodes that saddle a face and use that value to shade the polygon.
Here we can also see that we need to index the time and meshLayers dimensions to obtain our 1D slice of data.
uxds_geoflow["v1"].nodal_average()[0][0].to_geodataframe()
| geometry | v1_nodal_average | |
|---|---|---|
| 0 | MultiPolygon([[[0.0, 58.28252410888672, 5.2137... | -0.003357 |
| 1 | MultiPolygon([[[5.213775634765625, 59.79991149... | -0.005317 |
| 2 | MultiPolygon([[[16.497974395751953, 62.0571365... | -0.009873 |
| 3 | MultiPolygon([[[29.138521194458008, 63.2698593... | -0.011219 |
| 4 | MultiPolygon([[[0.0, 61.001914978027344, 5.342... | -0.006898 |
| ... | ... | ... |
| 3835 | MultiPolygon([[[63.31489562988281, -38.6694831... | -0.047156 |
| 3836 | MultiPolygon([[[52.8786506652832, -32.05970001... | -0.513393 |
| 3837 | MultiPolygon([[[55.743770599365234, -32.611831... | -0.398253 |
| 3838 | MultiPolygon([[[61.32698440551758, -33.4846153... | -0.269892 |
| 3839 | MultiPolygon([[[67.02494812011719, -34.1040725... | -0.196878 |
3840 rows × 2 columns
Vector Polygon Plots
uxds_mpas["bottomDepth"].plot.polygons()
/home/runner/miniconda3/envs/cookbook-dev/lib/python3.10/site-packages/uxarray/plot/dataarray_plot.py:402: UserWarning: Including Antimeridian Polygons may lead to visual artifacts. It is suggested to keep 'exclude_antimeridian' set to True.
warnings.warn(